bitkeeper revision 1.1159.1.148 (4142fe723Wt2mBhN5bsk_saNcZmnxg)
authoriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Sat, 11 Sep 2004 13:32:34 +0000 (13:32 +0000)
committeriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>
Sat, 11 Sep 2004 13:32:34 +0000 (13:32 +0000)
Live migration shadow table support for writable page tables.

xen/arch/x86/domain.c
xen/arch/x86/memory.c
xen/arch/x86/shadow.c
xen/arch/x86/traps.c
xen/include/asm-x86/shadow.h

index daca9114a94aa8ff4652a6ef2c6231ae4c9b2a51..d0ae459aa08f9a55c3a998be077ad535fdc2ab87 100644 (file)
@@ -869,11 +869,13 @@ int construct_dom0(struct domain *p,
 
     set_bit(DF_CONSTRUCTED, &p->flags);
 
+    new_thread(p, dsi.v_kernentry, vstack_end, vstartinfo_start);
+
 #if 0 /* XXXXX DO NOT CHECK IN ENABLED !!! (but useful for testing so leave) */
-    shadow_mode_enable(&p->mm, SHM_test); 
+    shadow_lock(&p->mm);
+    shadow_mode_enable(p, SHM_test); 
+    shadow_unlock(&p->mm);
 #endif
 
-    new_thread(p, dsi.v_kernentry, vstack_end, vstartinfo_start);
-
     return 0;
 }
index 90faa65119565129ef6d1926f39ce9b515236afc..cdaa1a89b191d02ed3ea363e2507021c7024830f 100644 (file)
@@ -1707,6 +1707,36 @@ void ptwr_reconnect_disconnected(void)
         MEM_LOG("ptwr: Could not update pte at %p\n", writable_pte);
         domain_crash();
     }
+
+    if ( unlikely(current->mm.shadow_mode) )
+    {
+       unsigned long spte;
+       unsigned long sstat = 
+           get_shadow_status(&current->mm, 
+                             ptwr_info[cpu].disconnected_pte >> PAGE_SHIFT);
+
+       if ( sstat & PSH_shadowed ) 
+       { 
+           int i;
+           unsigned long spfn = sstat & PSH_pfn_mask;
+           l1_pgentry_t *sl1e = map_domain_mem( spfn << PAGE_SHIFT );
+           
+           for( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) {
+               l1pte_no_fault( &current->mm, 
+                               &l1_pgentry_val(
+                                   ptwr_info[cpu].disconnected_page[i]),
+                               &l1_pgentry_val(sl1e[i]) );
+           }
+           unmap_domain_mem( sl1e );
+           put_shadow_status(&current->mm);
+       } 
+
+       l1pte_no_fault( &current->mm,
+                       &pte, &spte );
+       __put_user(spte, (unsigned long *)&shadow_linear_pg_table
+                  [ptwr_info[cpu].disconnected_l1va>>PAGE_SHIFT] );
+    }
+
     __flush_tlb_one(ptwr_info[cpu].disconnected_l1va);
     PTWR_PRINTK(PP_A, ("[A] disconnected_l1va at %p now %08lx\n",
                        writable_pte, pte));
@@ -1752,6 +1782,37 @@ void ptwr_flush_inactive(void)
         MEM_LOG("ptwr: Could not update pte at %p\n", writable_pte);
         domain_crash();
     }
+
+    if ( unlikely(current->mm.shadow_mode) )
+    {
+       unsigned long spte;
+       unsigned long sstat = 
+           get_shadow_status(&current->mm, 
+                             ptwr_info[cpu].writable_pte >> PAGE_SHIFT);
+
+       if ( sstat & PSH_shadowed ) 
+       { 
+           int i;
+           unsigned long spfn = sstat & PSH_pfn_mask;
+           l1_pgentry_t *sl1e = map_domain_mem( spfn << PAGE_SHIFT );
+           
+           for( i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++ ) {
+               l1pte_no_fault( &current->mm, 
+                               &l1_pgentry_val(
+                                   ptwr_info[cpu].writable_page[i]),
+                               &l1_pgentry_val(sl1e[i]) );
+                                              
+           }
+           unmap_domain_mem( sl1e );
+           put_shadow_status(&current->mm);
+       } 
+
+       l1pte_no_fault( &current->mm,
+                       &pte, &spte );
+       __put_user(spte, (unsigned long *)&shadow_linear_pg_table
+                  [ptwr_info[cpu].writable_l1va>>PAGE_SHIFT] );
+    }
+
     __flush_tlb_one(ptwr_info[cpu].writable_l1va);
     PTWR_PRINTK(PP_I, ("[I] disconnected_l1va at %p now %08lx\n",
                        writable_pte, pte));
@@ -1778,6 +1839,9 @@ int ptwr_do_page_fault(unsigned long addr)
          (__get_user(pte, (unsigned long *)
                      &linear_pg_table[addr >> PAGE_SHIFT]) == 0) )
     {
+       if( (pte & _PAGE_RW) && (pte & _PAGE_PRESENT) )
+           return 0; /* we can't help. Maybe shadow mode can? */
+
         pfn = pte >> PAGE_SHIFT;
 #if 0
         PTWR_PRINTK(PP_ALL, ("check pte %08lx = pfn %08lx for va %08lx\n", pte,
@@ -1862,7 +1926,11 @@ int ptwr_do_page_fault(unsigned long addr)
                         &linear_pg_table[addr>>PAGE_SHIFT]);
                 domain_crash();
             }
-            return 1;
+
+           if( unlikely(current->mm.shadow_mode) )
+               return 0;  /* fall through to shadow mode to propagate */
+           else
+               return 1;
         }
     }
     return 0;
index d909d6408597ead1945f8f5ab46a7777f47bb115..8f784a69e8208442e5742aa15da0ed7c0fc04bb3 100644 (file)
@@ -660,14 +660,14 @@ int shadow_fault( unsigned long va, long error_code )
     // write back updated gpte
     // XXX watch out for read-only L2 entries! (not used in Linux)
     if ( unlikely( __put_user( gpte, (unsigned long*)&linear_pg_table[va>>PAGE_SHIFT])) )
-        BUG();  // fixme!
+        domain_crash();  // fixme!
 
     if ( unlikely( __put_user( spte, (unsigned long*)&shadow_linear_pg_table[va>>PAGE_SHIFT])) )
     { 
         // failed:
         //  the L1 may not be shadowed, or the L2 entry may be insufficient
 
-        unsigned long gpde, spde, gl1pfn, sl1pfn;
+        unsigned long gpde, spde, gl1pfn, sl1pfn, sl1ss;
 
         SH_VVLOG("3: not shadowed or l2 insufficient gpte=%08lx  spte=%08lx",gpte,spte );
 
@@ -675,8 +675,8 @@ int shadow_fault( unsigned long va, long error_code )
 
         gl1pfn = gpde>>PAGE_SHIFT;
 
-        
-        if ( ! (sl1pfn=__shadow_status(&current->mm, gl1pfn) ) )
+        sl1ss = __shadow_status(&current->mm, gl1pfn);
+        if ( ! (sl1ss & PSH_shadowed) )
         {
             // this L1 is NOT already shadowed so we need to shadow it
             struct pfn_info *sl1pfn_info;
@@ -719,6 +719,7 @@ int shadow_fault( unsigned long va, long error_code )
 
             SH_VVLOG("4b: was shadowed, l2 missing ( %08lx )",sl1pfn);
 
+            sl1pfn = sl1ss & PSH_pfn_mask;
             l2pde_general( m, &gpde, &spde, sl1pfn );
 
             linear_l2_table[va>>L2_PAGETABLE_SHIFT] = mk_l2_pgentry(gpde);
index 800e66df1a985447fec3111a39359987177a86e9..d63c5fd88085b5f2d743de7ea8f9b48520ffb4fc 100644 (file)
@@ -121,11 +121,31 @@ void show_guest_stack()
     
 }
 
-void show_stack(unsigned long *esp)
+void show_trace(unsigned long *esp)
 {
     unsigned long *stack, addr;
     int i;
 
+    printk("Call Trace from ESP=%p: ", esp);
+    stack = esp;
+    i = 0;
+    while (((long) stack & (STACK_SIZE-1)) != 0) {
+        addr = *stack++;
+        if (kernel_text_address(addr)) {
+            if (i && ((i % 6) == 0))
+                printk("\n   ");
+            printk("[<%08lx>] ", addr);
+            i++;
+        }
+    }
+    printk("\n");
+}
+
+void show_stack(unsigned long *esp)
+{
+    unsigned long *stack;
+    int i;
+
     printk("Stack trace from ESP=%p:\n", esp);
 
     stack = esp;
@@ -142,19 +162,7 @@ void show_stack(unsigned long *esp)
     }
     printk("\n");
 
-    printk("Call Trace from ESP=%p: ", esp);
-    stack = esp;
-    i = 0;
-    while (((long) stack & (STACK_SIZE-1)) != 0) {
-        addr = *stack++;
-        if (kernel_text_address(addr)) {
-            if (i && ((i % 6) == 0))
-                printk("\n   ");
-            printk("[<%08lx>] ", addr);
-            i++;
-        }
-    }
-    printk("\n");
+    show_trace( esp );
 }
 
 void show_registers(struct pt_regs *regs)
index 5a1994cabbb4a720444bf667612862608bdadf79..60b2ef3ba9d0ac9e84e343d7399462efd5ad50d3 100644 (file)
@@ -118,13 +118,18 @@ static inline int __mark_dirty( struct mm_struct *m, unsigned int mfn )
     }
     else
     {
-        extern void show_traceX(void);
         SH_LOG("mark_dirty OOR! mfn=%x pfn=%x max=%x (mm %p)",
                mfn, pfn, m->shadow_dirty_bitmap_size, m );
-        SH_LOG("dom=%u caf=%08x taf=%08x\n", 
-               frame_table[mfn].u.inuse.domain->domain,
+        SH_LOG("dom=%p caf=%08x taf=%08x\n", 
+               frame_table[mfn].u.inuse.domain,
                frame_table[mfn].count_info, 
                frame_table[mfn].u.inuse.type_info );
+               {
+                       extern void show_trace(unsigned long *esp);             
+                       unsigned long *esp;
+                       __asm__ __volatile__ ("movl %%esp,%0" : "=r" (esp) : );
+                       show_trace(esp);
+               }
     }
 
     return rc;
@@ -134,7 +139,7 @@ static inline int __mark_dirty( struct mm_struct *m, unsigned int mfn )
 static inline int mark_dirty( struct mm_struct *m, unsigned int mfn )
 {
     int rc;
-    ASSERT(local_irq_is_enabled());
+    //ASSERT(local_irq_is_enabled());
     //if(spin_is_locked(&m->shadow_lock)) printk("+");
     shadow_lock(m);
     rc = __mark_dirty( m, mfn );
@@ -388,7 +393,7 @@ static inline unsigned long get_shadow_status( struct mm_struct *m,
        independnetly. 
     */
 
-    ASSERT(local_irq_is_enabled());
+    //ASSERT(local_irq_is_enabled());
     //if(spin_is_locked(&m->shadow_lock)) printk("*");
     shadow_lock(m);
 
@@ -585,7 +590,7 @@ static inline void shadow_mk_pagetable( struct mm_struct *mm )
 
     if ( unlikely(mm->shadow_mode) )
     {
-        ASSERT(local_irq_is_enabled());
+        //ASSERT(local_irq_is_enabled());
         shadow_lock(mm);
         __shadow_mk_pagetable(mm);
         shadow_unlock(mm);